/* 
*  Copyright (C) 2009-2010 WCG Project
*
*  This program is free software; you can redistribute it and/or modify it
*  under the terms of the GNU General Public License as published by the
*  Free Software Foundation; either version 2 of the License, or (at
*  your option) any later version.
*
*  This program is distributed in the hope that it will be useful, but
*  WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
*  General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software Foundation,
*  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*  In addition, as a special exception, the author gives permission to
*  link the code of this program with the Half-Life Game Engine ("HL
*  Engine") and Modified Game Libraries ("MODs") developed by Valve,
*  L.L.C ("Valve"). You must obey the GNU General Public License in all
*  respects for all of the code used other than the HL Engine and MODs
*  from Valve. If you modify this file, you may extend this exception
*  to your version of the file, but you are not obligated to do so. If
*  you do not wish to do so, delete this exception statement from your
*  version.
*/




new Float:g_VampiricEmbraceDamageCache[33]


new const Float:p_vembrace[5]			= {0.06, 0.12, 0.18, 0.24, 0.30}		// Vampiric Embrace
new const Float:p_resurrect[5]			= {0.5, 0.625, 0.75, 0.875, 1.0}		// Resurrect
new const p_fortitude[5]				= { 8, 16, 24, 32, 40 }					// Fortitude
new const Float:p_smite[5]				= {0.15, 0.20, 0.25, 0.30, 0.35}		// Smite
new const p_bindingheal[5]				= {20, 25, 30, 35, 40}
new const p_bindingheal_manacost[5]		= {20, 28, 36, 44, 52}					// binding heal mana cost



PRIEST_InitSkills()
{
	SM_InitSkill( SKILL_VAMPIRICEMBRACE, CLASS_PRIEST, SKILL_TYPE_TRAINABLE, sizeof(p_vembrace) )
	SM_InitSkill( SKILL_FORTITUDE, CLASS_PRIEST, SKILL_TYPE_TRAINABLE, sizeof(p_fortitude), 5 )
	SM_InitSkill( SKILL_SMITE, CLASS_PRIEST, SKILL_TYPE_TRAINABLE, sizeof(p_smite), 1, 3 )
	SM_InitSkill( SKILL_RESURRECT, CLASS_PRIEST, SKILL_TYPE_TRAINABLE, sizeof(p_resurrect), 1, 60 )
	SM_InitSkill( SKILL_INNERFIRE, CLASS_PRIEST, SKILL_TYPE_TRAINABLE, 5, 10 )
	SM_InitSkill( ULTIMATE_BINDINGHEAL, CLASS_PRIEST, SKILL_TYPE_ULTIMATE, sizeof(p_bindingheal), 10, 5 )
}



/*
//------------------------------------
// PRIEST_TriggerAbility
//
//------------------------------------
PRIEST_TriggerAbility( id, iSkillID )
{

}
*/


//------------------------------------
// PRIEST_TriggerUltimate
//
//------------------------------------
public PRIEST_TriggerUltimate( id, iSkillID )
{
	if( iSkillID == ULTIMATE_BINDINGHEAL )
	{
		if( PLAYER_CastSpell( id, ULTIMATE_BINDINGHEAL, CAST_NORMAL, _, _, _, CAST_SIMULATE ) ) 
		{
			new iSkillLevel = SM_GetSkillLevel( id, ULTIMATE_BINDINGHEAL )
			new iTargetID = UTIL_GetUserNearAim( id, PlayerInfo[id][PI_TeamID] )

			new param[3]
			param[0] = id
			param[1] = iTargetID
			param[2] = iSkillLevel
			
			PLAYER_CastSpell( id, ULTIMATE_BINDINGHEAL, CAST_NORMAL, "_SPELL_BindingHeal", param, 3 )
		}
	}
}


//------------------------------------
// PRIEST_Heartbeat
//
// This will only be called while the player is alive and freezetime is false
//------------------------------------
public PRIEST_Heartbeat( id )
{
	static bToggle
	
	if( g_VampiricEmbraceDamageCache[id] )
		PRIEST_VE_DistributeHealth( id )


	if( bToggle )
		PRIEST_CheckResurections( id )

	bToggle ^= 1
}



//------------------------------------
// PRIEST_SkillsOffensive
//
//------------------------------------
public PRIEST_SkillsOffensive( iAttacker, iVictim, iWeapon, &iDamage, iDamageType )
{
	static iSkillLevel

	// Inner Fire
	iSkillLevel = SM_GetSkillLevel( iAttacker, SKILL_INNERFIRE )
	if( iDamage && iSkillLevel > 0 && (iDamageType & (DMG_BULLET|DMG_SLASH|DMG_HEGRENADE)) )
		iDamage += floatround( float( iDamage ) * (0.10 * iSkillLevel / 5) )


	// Smite
	iSkillLevel = SM_GetSkillLevel( iAttacker, SKILL_SMITE )
	if( iSkillLevel > 0 && (iDamageType & (DMG_BULLET|DMG_SLASH)) )
	{
		if( random_float( 0.0, 1.0 ) <= p_smite[iSkillLevel-1] )
		{
			new param[2]
			param[0] = iAttacker
			param[1] = iVictim
			PLAYER_CastSpell( iAttacker, SKILL_SMITE, CAST_PASSIVE, "_SPELL_Smite", param, 2 )
		}
	}
}



//------------------------------------
// PRIEST_SkillsDefensive
//
//------------------------------------
public PRIEST_SkillsDefensive( iAttacker, iVictim, &iDamage, iWeapon, iDamageType )
{
	static iSkillLevel
	
	// Inner Fire
	iSkillLevel = SM_GetSkillLevel( iVictim, SKILL_INNERFIRE )
	if( iDamage && iSkillLevel > 0 )
		iDamage -= floatround( float( iDamage ) * (0.15 * iSkillLevel / 5) )
}




//--------------------------------------------------------------------------------------------------------------------------
// Vampiric Embrace


//------------------------------------
// PRIEST_VampiricEmbrace
//
//------------------------------------
PRIEST_VampiricEmbrace( iAttacker, Float:fDamage, bool:GiveMaskBonus )
{
	new iSkillLevel = SM_GetSkillLevel( iAttacker, SKILL_VAMPIRICEMBRACE )
	if( fDamage <= 0.0 || iSkillLevel <= 0 )
		return
	
	g_VampiricEmbraceDamageCache[iAttacker] += fDamage

	new iBonusHealth = floatround( fDamage * (p_vembrace[iSkillLevel-1] + ((GiveMaskBonus) ? 0.05 : 0.0) ) )

	if( PLAYER_Heal( iAttacker, iBonusHealth ) )
	{
		iBonusHealth <<= 2
		SHARED_Glow( iAttacker, COLOR_RGB( 0, ( iBonusHealth ), 0 ) )
		EFFECT_ScreenFade( iAttacker, 0.25, 0.1, COLOR_RGBA(0, 255, 0, min(iBonusHealth, 30)) )
	}
}



//------------------------------------
// PRIEST_VE_DistributeHealth
//
// Called once per second from heartbeat function if the cache contains any damage done
//------------------------------------
PRIEST_VE_DistributeHealth( id )
{
	static vOrigin[3], vTargetOrigin[3]

	new iTargetID, iDistance
	new iSkillLevel = SM_GetSkillLevel( id, SKILL_VAMPIRICEMBRACE )
	new iHealAmount = floatround( g_VampiricEmbraceDamageCache[id] * (0.10 * iSkillLevel / sizeof(p_vembrace)) )
	new iTargetTeam = PlayerInfo[id][PI_TeamID]
	
	g_VampiricEmbraceDamageCache[id] = 0.0

	get_user_origin( id, vOrigin )
	
	for( new i = 0 ; i < g_NumTeamPlayers[iTargetTeam] ; i++ )
	{
		iTargetID = g_SortedTeams[iTargetTeam][i]
		
		if( !is_user_alive(iTargetID) || iTargetID == id )
			continue

		get_user_origin( iTargetID, vTargetOrigin )
		iDistance = get_distance( vOrigin, vTargetOrigin )

		if( iDistance < 400.0 )
			PLAYER_Heal( iTargetID, iHealAmount, id )
	}
}




//--------------------------------------------------------------------------------------------------------------------------
// Fortitude


//------------------------------------
// PRIEST_BuffFortitude
//
//------------------------------------
public _PRIEST_BuffFortitude()
{
	new iBufferID_T, iBufferID_CT, iSkillLevel_T, iSkillLevel_CT, iSkillLevel
	
	for( new id = 1 ; id <= GameInfo[GI_MaxPlayers] ; id++ )
	{
		if( !is_user_alive( id ) )
			continue
		
		if( PlayerInfo[id][PI_Class] != CLASS_PRIEST )
			continue
		
		iSkillLevel = SM_GetSkillLevel( id, SKILL_FORTITUDE )
		
		switch( PlayerInfo[id][PI_TeamID] )
		{
			case TEAM_T:
			{
				if( iSkillLevel > iSkillLevel_T )
					iBufferID_T = id
			}

			case TEAM_CT:
			{
				if( iSkillLevel > iSkillLevel_CT )
					iBufferID_CT = id
			}
		}
	}

	if( iBufferID_T )
		PRIEST_Fortitude( iBufferID_T )

	if( iBufferID_CT )
		PRIEST_Fortitude( iBufferID_CT )
}


//------------------------------------
// PRIEST_Fortitude
//
//------------------------------------
PRIEST_Fortitude( id )
{
	new iTargetID

	if( !is_user_alive(id) )
		return
	
	new iSkillLevel = SM_GetSkillLevel( id, SKILL_FORTITUDE )
	if( iSkillLevel <= 0 )
		return

	new iFortitudeBonus = p_fortitude[iSkillLevel-1]

	new iTargetTeam = PlayerInfo[id][PI_TeamID]

	for( new i = 0 ; i < g_NumTeamPlayers[iTargetTeam] ; i++ )
	{
		iTargetID = g_SortedTeams[iTargetTeam][i]
		
		if( !is_user_alive(iTargetID) )
			continue

		if( PlayerBuffInfo[iTargetID][BUFF_Fortitude] != 0 )
			continue

		PlayerBuffInfo[iTargetID][BUFF_Fortitude] = iFortitudeBonus

		new iHealth = get_user_health( iTargetID )
		fm_set_user_health( iTargetID, iHealth + iFortitudeBonus )

		SHARED_Glow( iTargetID, COLOR_RGB( 150, 150, 150 ) )
		client_cmd( iTargetID, "speak %s", g_szSounds[SOUND_FORTITUDE] )
		if( iTargetID == id )
			client_print( iTargetID, print_chat, "You gain Power Word: Fortitude Rank %d.", iSkillLevel )
		else
			client_print( iTargetID, print_chat, "%s casts Power Word: Fortitude Rank %d.", PlayerInfo[id][PI_PlayerName], iSkillLevel )
	}
}





//--------------------------------------------------------------------------------------------------------------------------
// Smite

#define SMITE_DAMAGE		20			// Amount of damage dealt with shadow strike


//------------------------------------
// _SPELL_Smite
//
// PLAYER_CastSpell callback
//		param[0] = Caster ID
//		param[1] = Victim ID
//------------------------------------
public _SPELL_Smite( const param[2] )
{
	static vVictimOrigin[3], vAttackerOrigin[3]

	new iAttacker	= param[0]
	new iVictim		= param[1]

	if( !PLAYER_CheckMagicHit( iAttacker, iVictim ) )
	{
		client_print( iAttacker, print_chat, "Your Smite was resisted by %s.", PlayerInfo[iVictim][PI_PlayerName] )
		client_print( iVictim, print_chat, "You resisted %s's Smite.", PlayerInfo[iAttacker][PI_PlayerName] )
		client_cmd( iAttacker, "spk %s", g_szSounds[SOUND_DISPELL] )
		return
	}
	
	get_user_origin( iAttacker, vAttackerOrigin )
	get_user_origin( iVictim, vVictimOrigin )
	
	Create_TE_EXPLOSION( vVictimOrigin, vVictimOrigin, g_spr_explode1, 10, 15, TE_EXPLFLAG_NOSOUND )

	EFFECT_ScreenFade( iVictim, 0.25, 0.25, COLOR_RGBA(128, 192, 0, 128) )
	SHARED_Glow( iVictim, COLOR_RGB( 64, 128, 0 ) )

	emit_sound( iVictim, CHAN_STATIC, g_szSounds[SOUND_HOLYBOLT], VOL_NORM, ATTN_NORM, 0, PITCH_NORM )

	// Damage the user
	PLAYER_MagicDamage( iVictim, iAttacker, SMITE_DAMAGE, CSW_SMITE )
}



//--------------------------------------------------------------------------------------------------------------------------
// Resurrect


//------------------------------------
// PRIEST_Resurrect
//
// This function is called every other second to see if there are people to resurrect
//------------------------------------
PRIEST_CheckResurections( id )
{
	static iDeadPlayers[33]

	new iNumDeadPlayers, iTargetID

	new iSkillLevel = SM_GetSkillLevel( id, SKILL_RESURRECT )
	if( iSkillLevel <= 0 )
		return

	if( SM_IsOnCooldown( id, SKILL_RESURRECT ) || GameInfo[GI_EndRound] )
		return

	new iManaCost = SM_GetManaCost( id, SKILL_RESURRECT )
	if( PlayerInfo[id][PI_Mana] < iManaCost )
		return

	new iTargetTeam = PlayerInfo[id][PI_TeamID]
	
	for( new i = 0 ; i < g_NumTeamPlayers[iTargetTeam] ; i++ )
	{
		iTargetID = g_SortedTeams[iTargetTeam][i]

		if( iTargetID == id )
			continue
		
		if( !is_user_connected( iTargetID) || is_user_alive( iTargetID ) )
			continue

		if( PlayerInfo[iTargetID][PI_RespawnBy] || PlayerInfo[iTargetID][PI_ChangingTeam] )
			continue

		iDeadPlayers[iNumDeadPlayers++] = iTargetID
	}
	
	if( iNumDeadPlayers <= 0 )
		return

	iTargetID = iDeadPlayers[random_num( 0, iNumDeadPlayers-1 )]

	PlayerInfo[iTargetID][PI_RespawnBy] = RESPAWN_RESURRECT
	PlayerInfo[iTargetID][PI_ResurrectLevel] = iSkillLevel
	PLAYER_Spawn( iTargetID )	// Respawn the user

	PlayerInfo[id][PI_fMana] -= float(SM_GetManaCost( id, SKILL_RESURRECT ))
	PlayerInfo[id][PI_Mana] = clamp( floatround(PlayerInfo[id][PI_fMana]), 0, PlayerInfo[id][PI_MaxMana] )

	SM_SetCooldown( id, SKILL_RESURRECT )
	
	client_print( iTargetID, print_chat, "%s %L", g_MODclient, iTargetID, "HAS_RESURRECTED_YOU", PlayerInfo[id][PI_PlayerName] )
	client_print( id, print_chat, "%s %L", g_MODclient, id, "YOU_HAVE_RESURRECTED", PlayerInfo[iTargetID][PI_PlayerName] )

	emit_sound( id, CHAN_VOICE, g_szSounds[SOUND_CAST_HOLY], VOL_NORM, ATTN_NORM, 0, PITCH_NORM )
}


//--------------------------------------------------------------------------------------------------------------------------
// Binding Heal

public _SPELL_BindingHeal( param[] )
{
	new iCasterID	= param[0]
	new iTargetID	= param[1]
	new iSkillLevel	= param[2]

	if( !is_user_alive( iCasterID ) )
		return

	// Heal the caster
	PLAYER_Heal( iCasterID, p_bindingheal[iSkillLevel-1], iCasterID )
	SHARED_Glow( iCasterID, COLOR_RGB(72, 150, 0) )
	emit_sound( iCasterID, CHAN_STATIC, g_szSounds[SOUND_FLASH_HEAL], VOL_NORM, ATTN_NORM, 0, PITCH_NORM )

	
	if( !is_user_alive( iTargetID ) )
		return

	// heal the target
	PLAYER_Heal( iTargetID, p_bindingheal[iSkillLevel-1], iCasterID )
	SHARED_Glow( iTargetID, COLOR_RGB(72, 150, 0) )
	emit_sound( iTargetID, CHAN_STATIC, g_szSounds[SOUND_FLASH_HEAL], VOL_NORM, ATTN_NORM, 0, PITCH_NORM )
}
